﻿using System.Diagnostics.Contracts;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Arachnophile
{
    /// <summary>
    /// Text processing extensions.
    /// </summary>
    public static class TextEx
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string Text(this IEnumerable<char> source)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result<string>() != null);

            if (source is string)
                return (string)source;
            else
            {
                var buffer = new StringBuilder();
                foreach (var c in source)
                    buffer.Append(c);
                return buffer.ToString();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        public static string Between(this string source, string left, string right)
        {
            Contract.Requires(source != null);
            Contract.Requires(left != null);
            Contract.Requires(right != null);
            Contract.Ensures(Contract.Result<string>() != null);

            var i = source.IndexOf(left);
            if (i == -1)
                return null;
            i = i + left.Length;
            var j = source.IndexOf(right, i + 10);
            if (j == -1)
                return null;
            return source.Substring(i, j - i);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns></returns>
        public static IEnumerable<string> Between(this IEnumerable<string> source, string left, string right)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result<IEnumerable<string>>() != null);

            return from x in source select x.Between(left, right);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="chars"></param>
        /// <returns></returns>
        public static string Remove(this IEnumerable<char> source, char[] chars)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result<string>() != null);

            return source.Where(c => !chars.Contains(c)).Text();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string Utf8(this byte[] source)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result<string>() != null);

            return Encoding.UTF8.GetString(source);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IEnumerable<string> Utf8(this IEnumerable<byte[]> source)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result<IEnumerable<string>>() != null);

            return source.Select(Utf8);
        }
    }
}
